﻿using Module.Common.Common.QiPuHelper;
using Module.Common.PubEvent;
using Prism.Events;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ServiceItem.Engine
{
    public class UcciInfo
    {
        private readonly IEventAggregator Ea;
        private List<UcciInfoLine> InfoList { get; set; }
        //private string Bestmove;    // 最佳着法
        //private string Ponder;  // 后续的最佳着法
        private string _InfoSource;

        private string InfoSource // 象棋引擎返回的多行字符串，进行解析后，保存到相应变量中。
        {

            get { return _InfoSource; }
            set
            {
                _InfoSource = value;
                InfoList.Clear();
                //Bestmove = "";
                //Ponder = "";
                if (!_InfoSource.Contains("info depth"))
                {
                    return;
                }
                string keystr = "bestmove"; // 最佳着法
                int start = _InfoSource.IndexOf(keystr);
                if (start > -1)
                {
                    string uccistr = InfoSource.Substring(start + keystr.Length, 5).Trim();
                    //Bestmove = UcciStrToCnStr(uccistr, GlobalValue.QiPan, false);
                }

                keystr = "ponder"; // 后续的最佳着法
                start = InfoSource.IndexOf(keystr);
                if (start > -1)
                {
                    string uccistr = InfoSource.Substring(start + keystr.Length, 5).Trim();
                    //Ponder = UcciStrToCnStr(uccistr, GlobalValue.QiPan, false);
                }

                int end = InfoSource.IndexOf("bestmove"); // 删除bestmove所在行
                string[] bufArr = InfoSource[..end].Trim().Split(Environment.NewLine); // 按行分割字符串为数组

                foreach (string str in bufArr)
                {
                    UcciInfoLine infoline = new()
                    {
                        InfoLineStr = str
                    };
                    InfoList.Add(infoline);
                }
            }
        }

        public UcciInfo(IEventAggregator ea)
        {
            InfoList = new List<UcciInfoLine>();
            this.Ea = ea;
            Ea.GetEvent<ServiceMessageEvent>().Subscribe(ReciewMessage,ThreadOption.BackgroundThread); // 进程选项为后台进程，目的：象棋引擎的计算需要时间，为不影响UI进程，所以设置在后台运行。
        }
        /// <summary>
        /// 订阅消息处理
        /// </summary>
        /// <param name="obj">消息体</param>
        private void ReciewMessage(ServiceMessage obj)
        {
            switch (obj.MessageName)
            {
                case "getBestStep":    // 有棋子移动动画执行完毕消息
                    InfoSource = XQEngine.CallEngine(obj.QiPanData_Message, obj.SideTag, 10, 5); // 调用象棋引擎，获得下一步着法信息
                    string beststr = GetBestMove(obj.QiPanData_Message, false);
                    DataTable dataTable = GetMoveDataTable(obj.QiPanData_Message);
                    if (beststr != null)
                    {
                        Ea.GetEvent<ServiceMessageEvent>().Publish(new ServiceMessage()
                        {
                            MessageName = "BestMoveOk",
                            Content = $"【{this.GetType().Name}】：{beststr}",
                            BestStepData=GetBestMoveStepData(obj.QiPanData_Message),
                            BestMoveData =dataTable,
                            SenderFrom = this.GetType().Name,
                            ModuleName=obj.ModuleName,
                        });
                    }
                    break;
                case "reStart": // 重新开局
                    break;
                default: break;
            }
        }
        /// <summary>
        /// 获取最佳着法，同时显示所有推荐着法的提示箭头
        /// </summary>
        /// <param name="showarrow">得到最佳着法后，是否在棋盘上显示指示箭头</param>
        /// <returns>最佳着法</returns>
        public string GetBestMove(in int[,] qipan, bool showarrow)
        {
            string str = "";
            if (InfoList.Count > 0)
            {
                int maxscore = InfoList.Max(x => x.Score);
                str = InfoList.FirstOrDefault(x => x.Score == maxscore).GetMove(qipan);
                str = $"最佳着法（{maxscore}分）： {str}";
            }
            else
            {
                str = $"最佳着法： {InfoSource}";
            }
            //if (showarrow || MainWindow.menuItem == GlobalValue.PERSON_PC) ShowArrows();
            return str;
        }
        public DataTable GetMoveDataTable(in int[,] qipan)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("id");
            dt.Columns.Add("score");
            dt.Columns.Add("movestr");
            if (InfoList.Count > 0)
            {
                foreach(UcciInfoLine ul in InfoList)
                {
                    DataRow dataRow = dt.NewRow();
                    dataRow[0] = InfoList.IndexOf(ul)+1;
                    dataRow[1] = ul.Score;
                    dataRow[2] = ul.GetMove(qipan);
                    dt.Rows.Add(dataRow);
                }
            }
            
            return dt;
        }
        private StepData GetBestMoveStepData(int[,] qipan)
        {
            if (InfoList.Count > 0)
            {
                int maxscore = InfoList.Max(x => x.Score);
                string str = InfoList.FirstOrDefault(x => x.Score == maxscore).UcciStrList.FirstOrDefault();
                return GetStep(str,qipan);
            }
            return null;
        }
        /// <summary>
        /// 将UCCI着法转换为step着法数据
        /// </summary>
        /// <param name="ucciStr">UCCI着法字符串，一般是从象棋引擎中取得</param>
        /// <param name="qipan">棋盘数据。此变量建议保留。</param>
        /// <returns></returns>
        private static StepData GetStep(string ucciStr, int[,] qipan)
        {
            ucciStr = ucciStr.Trim();
            if (ucciStr.Length != 4)
            {
                return null;
            }
            string cols = "abcdefghi";
            string rows = "9876543210";
            int x0 = cols.IndexOf(ucciStr[0]);  // 现位置
            int y0 = rows.IndexOf(ucciStr[1]);
            int x1 = cols.IndexOf(ucciStr[2]);  // 目标位置
            int y1 = rows.IndexOf(ucciStr[3]);
            int qizi = qipan[x0, y0];
            int dieQiZi = qipan[x1, y1];
            StepData step = new();
            step.SetStepData(qizi, x0, y0, x1, y1, dieQiZi);
            return step;
        }
        /// <summary>
        /// 显示所有推荐着法的提示箭头。
        /// 提示箭头的数量限定为5个。
        /// </summary>
        private void ShowArrows()
        {
            //GlobalValue.arrows.HideAllPath();
            int arrowCount = 5;
            //
            if (InfoList.Count > 0)
            {
                List<List<System.Drawing.Point>> points = new();
                foreach (UcciInfoLine p in InfoList)
                {
                    points.Add(p.GetPoint());
                }
                //int arrowCount = (points.Count > Settings.Default.ArrowsMaxNum) ? Settings.Default.ArrowsMaxNum : points.Count; // 提示箭头的数量限定为5个。超过5个时，多余的没有用，且界面太乱。
                for (int i = 0; i < arrowCount; i++)
                {
                    bool sameTargetPoint = false;
                    if (i > 0)
                    {
                        for (int j = 0; j < i; j++)
                        {
                            if (points[i][1].X == points[j][1].X && points[i][1].Y == points[j][1].Y)
                            {
                                sameTargetPoint = true;
                                break;
                            }
                        }
                    }
                    //string tipInfo = $"{InfoList[i].Score}分{Environment.NewLine}{InfoList[i].GetMove()}";
                    //GlobalValue.arrows.SetPathData(i, points[i][0], points[i][1], sameTargetPoint, tipInfo);
                }
            }
            //GlobalValue.arrows.ShowAllPath();
        }
        //public CustomClass.Qipu.StepCode GetBestSetp()
        //{
        //    if (InfoList.Count > 0) return InfoList[0].FirstStep;
        //    return null;
        //}
    }
}
